#include "stdafx.h"
#include "GeoLocation.h"

CGeoLoc::CGeoLoc(GeoSystems sys, double x, double y, double z, double or, int zone, bool north) :
	m_geoSystem(sys), m_geoX(x), m_geoY(y), m_geoZ(z), m_orientation(or), m_geoZone(zone), m_geoNorth(north)
{
	TRACE("CGeoLoc::CGeoLoc");

	switch (sys)
	{
	case GS_UTM:		m_spatialRef.SetUTM(m_geoZone, m_geoNorth); break;
	case GS_EPSG28992:	m_spatialRef.importFromEPSG(28992); break;
	case GS_EPSG3857:	m_spatialRef.importFromEPSG(3857); break;
	case GS_EPSG4326:	m_spatialRef.importFromEPSG(4326); break;
	case GS_MERCATOR:	m_spatialRef.SetMercator(0.0, 0.0, 1.0, false, false); break;
	}
}

CGeoLoc::~CGeoLoc(void)
{
	TRACE("CGeoLoc::~CGeoLoc");
}


void CGeoLoc::ChangeSystem(GeoSystems sys)
{
	TRACE("CGeoLoc::ChangeSystem");

	if (m_geoSystem == sys)
		return;

	OGRSpatialReference out;
	OGRCoordinateTransformation *trans;

	switch (sys)
	{
	case GS_UTM:		m_geoZone = m_spatialRef.GetUTMZone(&m_geoNorth);
						out.SetUTM(m_geoZone, m_geoNorth); break;
	case GS_EPSG28992:	out.importFromEPSG(28992); break;
	case GS_EPSG3857:	out.importFromEPSG(3857); break;
	case GS_EPSG4326:	out.importFromEPSG(4326); break;
	case GS_MERCATOR:	out.SetMercator(0.0, 0.0, 1.0, false, false); break;
	}
	trans = OGRCreateCoordinateTransformation(&m_spatialRef, &out);

	if( trans == NULL || !trans->Transform(1, &m_geoX, &m_geoY, &m_geoZ))
		AfxMessageBox("Transform of point failed." );
	else
	{
		m_spatialRef = out;
		m_geoSystem = sys;
	}
}




void CGeoLoc::SetOffset(CGeoLoc *refpos)
{
	TRACE("CGeoLoc::SetOffset");

	OGRSpatialReference out;
	OGRCoordinateTransformation *trans;

	out.SetMercator(0.0, 0.0, 1.0, 0.0, 0.0);
	double xref = refpos->m_geoX,  
	       yref = refpos->m_geoY;

	// calculate (if needed) the lat lon of the refpos
	if (refpos->m_geoSystem != GS_MERCATOR)
	{
		trans = OGRCreateCoordinateTransformation(&refpos->m_spatialRef, &out);

		if( trans == NULL || !trans->Transform(1, &xref, &yref))
		{
			AfxMessageBox("Transform of point failed." );
			return;
		}
	}

	// create the mercator system from refpos and calculate this coordinates offset
	out.SetMercator(0.0, 0.0, 1.0, 0.0, 0.0);
	trans = OGRCreateCoordinateTransformation(&m_spatialRef, &out);

	double x = m_geoX,
	y = m_geoY;

	if( trans == NULL || !trans->Transform(1, &x, &y))
		AfxMessageBox("Transform of point failed." );
	else
	{
		m_yOffset = x - xref;
		m_xOffset = y - yref;
	}
}


void CGeoLoc::ConvertDeltaToLatLon(int nr, double *x, double *y)
{
	TRACE("CGeoLoc::ConvertDeltaToLatLon");

	double tx = m_geoX,  
		   ty = m_geoY;

	OGRSpatialReference out, in;
	OGRCoordinateTransformation *trans;
	OGRErr ogrErr;
 
//	GDALSetConfigOption( "GDAL_DATA", "C:\\_Projecten\\CityGML\\gdal-1.7.3\\data" );
    ogrErr = out.importFromEPSG(4326);

/*	// calculate (if needed) the lat lon origin used for this reference coordinate 
	if (m_geoSystem != GS_EPSG4326)
	{
		trans = OGRCreateCoordinateTransformation(&m_spatialRef, &out);

		if( trans == NULL || !trans->Transform(1, &tx, &ty))
		{
			AfxMessageBox("Setting the basic mercator position failed." );
			return;
		}
	}
	//set the basic mercator projection from the reference coordinate
*/

	// convert the localpoint to UTM if this is not yet in UTM
	double xref = m_geoX, yref = m_geoY;
	if (m_geoSystem != GS_MERCATOR)
	{
//		m_geoZone = m_spatialRef.GetUTMZone(&m_geoNorth);
		ogrErr = in.SetMercator(0.0, 0.0, 1.0, 0.0, 0.0);
//      ogrErr = in.importFromEPSG(3857);
//		in.SetUTM(m_geoZone, m_geoNorth);
		trans = OGRCreateCoordinateTransformation(&m_spatialRef, &in);

		if( trans == NULL || !trans->Transform(1, &xref, &yref))
			AfxMessageBox("Transform of point failed." );
	}

	// convert the deltas to absolute coordinates in UTM
	for (int i=0; i < nr; i++)
	{
		x[i] += xref;
		y[i] += yref;
	}
	
	//create and execute the transform get the delta positions in lat and long values
	trans = OGRCreateCoordinateTransformation(&in, &out);
	if( trans == NULL || !trans->Transform(nr, x, y))
		AfxMessageBox("Transform of point failed." );
}
